//
// Created by Tony on 2024/6/15.
//

#ifndef RUNTIME_MUL_H
#define RUNTIME_MUL_H

#include "Instruction.h"

namespace Runtime {

class MUL final : public NoOperandsInstruction {

    static RtTaggedValue mul(RtTaggedValue a, RtTaggedValue b) {
        if (a.tag == RtValueTag::INT64) {
            if (b.tag == RtValueTag::INT64) {
                return RtTaggedValue(a.value.int64 * b.value.int64);
            }
            if (b.tag == RtValueTag::FLT64) {
                return RtTaggedValue(static_cast<double>(a.value.int64) * b.value.flt64);
            }
            // TODO: no support
        } else if (a.tag == RtValueTag::FLT64) {
            if (b.tag == RtValueTag::INT64) {
                return RtTaggedValue(a.value.flt64 * static_cast<double>(b.value.int64));
            }
            if (b.tag == RtValueTag::FLT64) {
                return RtTaggedValue(a.value.flt64 * b.value.flt64);
            }
            // TODO: no support
        }
        return {};
    }

public:
    MUL() : NoOperandsInstruction(__func__, OpCode::MUL) {}

    void execute(RtData::Frame& frame) override {
        auto right = frame.popValue();
        auto left = frame.popValue();
        frame.pushValue(mul(left, right));
    }
};

} // namespace Runtime

#endif // RUNTIME_MUL_H